package wxdb.index.btree;

import java.io.Serializable;

import wxdb.query.Constant;
import wxdb.record.TableInfo;

public class BTreeDir implements Serializable{
	
	TableInfo ti;
	BTreePage content;
	
	public BTreeDir(int pid, TableInfo ti){
		this.ti = ti;
		this.content = new BTreePage(pid, ti);
	}
	
	public int search(Constant searchKey){
		int pid = findChildDirPid(searchKey);
		while(content.getFlag() > 0){
			content = new BTreePage(pid, ti);
			pid = findChildDirPid(searchKey);
		}
		return pid;
	}
	
	public DirEntry insert(DirEntry de){
		if(content.getFlag() == 0)
			return insertEntry(de);		//get to the lowest layer
		int pid = findChildDirPid(de.getSearchKey());
		BTreeDir btd = new BTreeDir(pid, ti);
		DirEntry de2 = btd.insert(de);
		if(de2 != null)
			return insertEntry(de2);	//inserting to son causes sons splitting
		else
			return null;				//no split
	}
	
	public DirEntry insertEntry(DirEntry de){
		int slot = content.findFirstSlotBefore(de.getSearchKey()) + 1;
		if(slot == 0)
			slot = 1;	//slot 0 is always the minimum
		content.insertDir(slot, de.getSearchKey(), de.getPid());
		if(!content.isFull())
			return null;
		int splitpos = content.getTotalSlotNum()/2;
		int flag = content.getFlag();
		Constant spltVal = content.getFldVal(splitpos, "dataval");
		int pid = content.split(splitpos, flag);
		return new DirEntry(spltVal, pid);
	}
	
	public void makeNewRoot(DirEntry de){
		Constant firstVal = content.getFldVal(0, "dataval");
		int flag = content.getFlag();
		int pid = content.split(0, flag);
		DirEntry oldRoot = new DirEntry(firstVal, pid);
		this.insert(oldRoot);
		this.insert(de);
		content.setFlag(flag+1);
	}
	
	public int findChildDirPid(Constant searchKey){
		int slot = content.findFirstSlotBefore(searchKey);
		Constant c = content.getFldVal(slot+1, "dataval");
		if(c.equals(searchKey) || slot<0)
			++slot;
		return content.getPid(slot);
	}
}
